//  -------------------- iSharePoint -------------------- //
// 
//  Company:	IT Complex, LLC
//  Project:	Smart.Common
//  File name:	CamlQueryBuilderItemGroupGroupable.cs
//  Developer:	Solomatov Igor
//  Created:	15.04.2012
// 
//  -------------------- iSharePoint -------------------- //

using System.Linq;

namespace Smart.Common.Entities
{
	/// <summary>
	/// QueryBuilder Query Item Group (And, Or, Where, OrderBy)
	/// </summary>
	public class CamlQueryBuilderItemGroupGroupable<TExecutorType> : CamlQueryBuilderItemGroup<TExecutorType>
		where TExecutorType : class
	{
		/// <summary>
		/// Option to group children by 2 in one set
		/// </summary>
		public bool GroupChildren { get; set; }

		/// <summary>
		/// Option to group children always (whether is 1 or many of them)
		/// </summary>
		public bool GroupAlways { get; set; }

		/// <summary>
		/// QueryBuilder Query Item Group (And, Or, Where, OrderBy)
		/// </summary>
		public CamlQueryBuilderItemGroupGroupable(string op, bool groupChildren, bool groupAlways)
			: base(op)
		{
			GroupChildren = groupChildren;
			GroupAlways = groupAlways;
		}

		/// <summary>
		/// Format QueryBuilder statement
		/// </summary>
		public override string FormatQuery()
		{
			var items = (GroupChildren
							? Children.CollapseInGroups<CamlQueryBuilderItem<TExecutorType>, CamlQueryBuilderItemGroup<TExecutorType>>
								(2, 2, Create, (group, item) => group.AddItem(item))
							: Children.Where(item => item != null).ToList());

			var filters = items.CastToString(string.Empty, item => item.FormatQuery());

			return
				filters.IsNullOrEmpty()
					? string.Empty
					: (!GroupAlways && items.Count == 1)
						? filters
						: string.Format("<{0}>{1}</{0}>", Op, filters);
		}

		/// <summary>
		/// Create group
		/// </summary>
		public override CamlQueryBuilderItemGroup<TExecutorType> Create()
		{
			// false: hack to reduce calls to CollapseInGroup
			return new CamlQueryBuilderItemGroupGroupable<TExecutorType>(Op, false, GroupAlways) { Group = this, Query = Query };
		}

		/// <summary>
		/// Return Cache code
		/// </summary>
		public override int GetCacheCode()
		{
			return base.GetCacheCode() ^ (GroupChildren.GetHashCode() << 5);
		}
	}
}